// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/domain_reliability/google_configs.h"

#include <memory>

#include "base/strings/string_util.h"
#include "net/base/url_util.h"

namespace domain_reliability {

namespace {

struct GoogleConfigParams {
  const char* hostname;
  bool include_subdomains;

  // If true, prepend a collector URL within https://|hostname|/.
  bool include_origin_specific_collector;

  // If true, also add a config for www.|hostname|.
  //
  // |include_subdomains| will be false in the extra config, but
  // |include_origin_specific_collector| will be respected, and will use the
  // www subdomain as the origin for the collector so it matches the config.
  bool duplicate_for_www;
};

const GoogleConfigParams kGoogleConfigs[] = {
    // Origins with subdomains and same-origin collectors. Currently, all
    // origins with same-origin collectors also run collectors on their www
    // subdomain. (e.g., both foo.com and www.foo.com.)
    {"google.ac", true, true, true},
    {"google.ad", true, true, true},
    {"google.ae", true, true, true},
    {"google.af", true, true, true},
    {"google.ag", true, true, true},
    {"google.al", true, true, true},
    {"google.am", true, true, true},
    {"google.as", true, true, true},
    {"google.at", true, true, true},
    {"google.az", true, true, true},
    {"google.ba", true, true, true},
    {"google.be", true, true, true},
    {"google.bf", true, true, true},
    {"google.bg", true, true, true},
    {"google.bi", true, true, true},
    {"google.bj", true, true, true},
    {"google.bs", true, true, true},
    {"google.bt", true, true, true},
    {"google.by", true, true, true},
    {"google.ca", true, true, true},
    {"google.cc", true, true, true},
    {"google.cd", true, true, true},
    {"google.cf", true, true, true},
    {"google.cg", true, true, true},
    {"google.ch", true, true, true},
    {"google.ci", true, true, true},
    {"google.cl", true, true, true},
    {"google.cm", true, true, true},
    {"google.cn", true, true, true},
    {"google.co.ao", true, true, true},
    {"google.co.bw", true, true, true},
    {"google.co.ck", true, true, true},
    {"google.co.cr", true, true, true},
    {"google.co.hu", true, true, true},
    {"google.co.id", true, true, true},
    {"google.co.il", true, true, true},
    {"google.co.im", true, true, true},
    {"google.co.in", true, true, true},
    {"google.co.je", true, true, true},
    {"google.co.jp", true, true, true},
    {"google.co.ke", true, true, true},
    {"google.co.kr", true, true, true},
    {"google.co.ls", true, true, true},
    {"google.co.ma", true, true, true},
    {"google.co.mz", true, true, true},
    {"google.co.nz", true, true, true},
    {"google.co.th", true, true, true},
    {"google.co.tz", true, true, true},
    {"google.co.ug", true, true, true},
    {"google.co.uk", true, true, true},
    {"google.co.uz", true, true, true},
    {"google.co.ve", true, true, true},
    {"google.co.vi", true, true, true},
    {"google.co.za", true, true, true},
    {"google.co.zm", true, true, true},
    {"google.co.zw", true, true, true},
    {"google.com.af", true, true, true},
    {"google.com.ag", true, true, true},
    {"google.com.ai", true, true, true},
    {"google.com.ar", true, true, true},
    {"google.com.au", true, true, true},
    {"google.com.bd", true, true, true},
    {"google.com.bh", true, true, true},
    {"google.com.bn", true, true, true},
    {"google.com.bo", true, true, true},
    {"google.com.br", true, true, true},
    {"google.com.by", true, true, true},
    {"google.com.bz", true, true, true},
    {"google.com.cn", true, true, true},
    {"google.com.co", true, true, true},
    {"google.com.cu", true, true, true},
    {"google.com.cy", true, true, true},
    {"google.com.do", true, true, true},
    {"google.com.ec", true, true, true},
    {"google.com.eg", true, true, true},
    {"google.com.et", true, true, true},
    {"google.com.fj", true, true, true},
    {"google.com.ge", true, true, true},
    {"google.com.gh", true, true, true},
    {"google.com.gi", true, true, true},
    {"google.com.gr", true, true, true},
    {"google.com.gt", true, true, true},
    {"google.com.hk", true, true, true},
    {"google.com.iq", true, true, true},
    {"google.com.jm", true, true, true},
    {"google.com.jo", true, true, true},
    {"google.com.kh", true, true, true},
    {"google.com.kw", true, true, true},
    {"google.com.lb", true, true, true},
    {"google.com.ly", true, true, true},
    {"google.com.mm", true, true, true},
    {"google.com.mt", true, true, true},
    {"google.com.mx", true, true, true},
    {"google.com.my", true, true, true},
    {"google.com.na", true, true, true},
    {"google.com.nf", true, true, true},
    {"google.com.ng", true, true, true},
    {"google.com.ni", true, true, true},
    {"google.com.np", true, true, true},
    {"google.com.nr", true, true, true},
    {"google.com.om", true, true, true},
    {"google.com.pa", true, true, true},
    {"google.com.pe", true, true, true},
    {"google.com.pg", true, true, true},
    {"google.com.ph", true, true, true},
    {"google.com.pk", true, true, true},
    {"google.com.pl", true, true, true},
    {"google.com.pr", true, true, true},
    {"google.com.py", true, true, true},
    {"google.com.qa", true, true, true},
    {"google.com.ru", true, true, true},
    {"google.com.sa", true, true, true},
    {"google.com.sb", true, true, true},
    {"google.com.sg", true, true, true},
    {"google.com.sl", true, true, true},
    {"google.com.sv", true, true, true},
    {"google.com.tj", true, true, true},
    {"google.com.tn", true, true, true},
    {"google.com.tr", true, true, true},
    {"google.com.tw", true, true, true},
    {"google.com.ua", true, true, true},
    {"google.com.uy", true, true, true},
    {"google.com.vc", true, true, true},
    {"google.com.ve", true, true, true},
    {"google.com.vn", true, true, true},
    {"google.cv", true, true, true},
    {"google.cz", true, true, true},
    {"google.de", true, true, true},
    {"google.dj", true, true, true},
    {"google.dk", true, true, true},
    {"google.dm", true, true, true},
    {"google.dz", true, true, true},
    {"google.ee", true, true, true},
    {"google.es", true, true, true},
    {"google.fi", true, true, true},
    {"google.fm", true, true, true},
    {"google.fr", true, true, true},
    {"google.ga", true, true, true},
    {"google.ge", true, true, true},
    {"google.gg", true, true, true},
    {"google.gl", true, true, true},
    {"google.gm", true, true, true},
    {"google.gp", true, true, true},
    {"google.gr", true, true, true},
    {"google.gy", true, true, true},
    {"google.hk", true, true, true},
    {"google.hn", true, true, true},
    {"google.hr", true, true, true},
    {"google.ht", true, true, true},
    {"google.hu", true, true, true},
    {"google.ie", true, true, true},
    {"google.im", true, true, true},
    {"google.iq", true, true, true},
    {"google.ir", true, true, true},
    {"google.is", true, true, true},
    {"google.it", true, true, true},
    {"google.it.ao", true, true, true},
    {"google.je", true, true, true},
    {"google.jo", true, true, true},
    {"google.jp", true, true, true},
    {"google.kg", true, true, true},
    {"google.ki", true, true, true},
    {"google.kz", true, true, true},
    {"google.la", true, true, true},
    {"google.li", true, true, true},
    {"google.lk", true, true, true},
    {"google.lt", true, true, true},
    {"google.lu", true, true, true},
    {"google.lv", true, true, true},
    {"google.md", true, true, true},
    {"google.me", true, true, true},
    {"google.mg", true, true, true},
    {"google.mk", true, true, true},
    {"google.ml", true, true, true},
    {"google.mn", true, true, true},
    {"google.ms", true, true, true},
    {"google.mu", true, true, true},
    {"google.mv", true, true, true},
    {"google.mw", true, true, true},
    {"google.ne", true, true, true},
    {"google.ne.jp", true, true, true},
    {"google.ng", true, true, true},
    {"google.nl", true, true, true},
    {"google.no", true, true, true},
    {"google.nr", true, true, true},
    {"google.nu", true, true, true},
    {"google.off.ai", true, true, true},
    {"google.pk", true, true, true},
    {"google.pl", true, true, true},
    {"google.pn", true, true, true},
    {"google.ps", true, true, true},
    {"google.pt", true, true, true},
    {"google.ro", true, true, true},
    {"google.rs", true, true, true},
    {"google.ru", true, true, true},
    {"google.rw", true, true, true},
    {"google.sc", true, true, true},
    {"google.se", true, true, true},
    {"google.sh", true, true, true},
    {"google.si", true, true, true},
    {"google.sk", true, true, true},
    {"google.sm", true, true, true},
    {"google.sn", true, true, true},
    {"google.so", true, true, true},
    {"google.sr", true, true, true},
    {"google.st", true, true, true},
    {"google.td", true, true, true},
    {"google.tg", true, true, true},
    {"google.tk", true, true, true},
    {"google.tl", true, true, true},
    {"google.tm", true, true, true},
    {"google.tn", true, true, true},
    {"google.to", true, true, true},
    {"google.tt", true, true, true},
    {"google.us", true, true, true},
    {"google.uz", true, true, true},
    {"google.vg", true, true, true},
    {"google.vu", true, true, true},
    {"google.ws", true, true, true},
    {"l.google.com", true, true, true},

    // google.com is a special case. We have a custom config for www.google.com,
    // so set duplicate_for_www = false.
    {"google.com", true, true, false},

    // Origins with subdomains and without same-origin collectors.
    {"2mdn.net", true, false, false},
    {"adgoogle.net", true, false, false},
    {"admeld.com", true, false, false},
    {"admob.biz", true, false, false},
    {"admob.co.in", true, false, false},
    {"admob.co.kr", true, false, false},
    {"admob.co.nz", true, false, false},
    {"admob.co.uk", true, false, false},
    {"admob.co.za", true, false, false},
    {"admob.com", true, false, false},
    {"admob.com.br", true, false, false},
    {"admob.com.es", true, false, false},
    {"admob.com.fr", true, false, false},
    {"admob.com.mx", true, false, false},
    {"admob.com.pt", true, false, false},
    {"admob.de", true, false, false},
    {"admob.dk", true, false, false},
    {"admob.es", true, false, false},
    {"admob.fi", true, false, false},
    {"admob.fr", true, false, false},
    {"admob.gr", true, false, false},
    {"admob.hk", true, false, false},
    {"admob.ie", true, false, false},
    {"admob.in", true, false, false},
    {"admob.it", true, false, false},
    {"admob.jp", true, false, false},
    {"admob.kr", true, false, false},
    {"admob.mobi", true, false, false},
    {"admob.no", true, false, false},
    {"admob.ph", true, false, false},
    {"admob.pt", true, false, false},
    {"admob.sg", true, false, false},
    {"admob.tw", true, false, false},
    {"admob.us", true, false, false},
    {"admob.vn", true, false, false},
    {"adwhirl.com", true, false, false},
    {"ampproject.com", true, false, false},
    {"ampproject.net", true, false, false},
    {"ampproject.org", true, false, false},
    {"android.com", true, false, false},
    {"cdn.ampproject.org", true, false, false},
    {"chromecast.com", true, false, false},
    {"chromeexperiments.com", true, false, false},
    {"chromestatus.com", true, false, false},
    {"chromium.org", true, false, false},
    {"clients6.google.com", true, false, false},
    {"cloudendpointsapis.com", true, false, false},
    {"dartmotif.com", true, false, false},
    {"dartsearch.net", true, false, false},
    {"doubleclick.com", true, false, false},
    {"doubleclick.ne.jp", true, false, false},
    {"doubleclick.net", true, false, false},
    {"doubleclickusercontent.com", true, false, false},
    {"fls.doubleclick.net", true, false, false},
    {"g.co", true, false, false},
    {"g.doubleclick.net", true, false, false},
    {"ggpht.com", true, false, false},
    {"gmodules.com", true, false, false},
    {"goo.gl", true, false, false},
    {"google-syndication.com", true, false, false},
    {"google.cat", true, false, false},
    {"google.info", true, false, false},
    {"google.jobs", true, false, false},
    {"google.net", true, false, false},
    {"google.org", true, false, false},
    {"google.stackdriver.com", true, false, false},
    {"googleadapis.com", true, false, false},
    {"googleadservices.com", true, false, false},
    {"googleadsserving.cn", true, false, false},
    {"googlealumni.com", true, false, false},
    {"googleapis.cn", true, false, false},
    {"googleapis.com", true, false, false},
    {"googleapps.com", true, false, false},
    {"googlecbs.com", true, false, false},
    {"googlecode.com", true, false, false},
    {"googlecommerce.com", true, false, false},
    {"googledrive.com", true, false, false},
    {"googleenterprise.com", true, false, false},
    {"googlefiber.com", true, false, false},
    {"googlefiber.net", true, false, false},
    {"googlegoro.com", true, false, false},
    {"googlehosted.com", true, false, false},
    {"googlepayments.com", true, false, false},
    {"googlesource.com", true, false, false},
    {"googlesyndication.com", true, false, false},
    {"googletagmanager.com", true, false, false},
    {"googletagservices.com", true, false, false},
    {"googleusercontent.com", true, false, false},
    {"googlezip.net", true, false, false},
    {"gstatic.cn", true, false, false},
    {"gstatic.com", true, false, false},
    {"gvt3.com", true, false, false},
    {"gvt9.com", true, false, false},
    {"picasa.com", true, false, false},
    {"recaptcha.net", true, false, false},
    {"stackdriver.com", true, false, false},
    {"waze.com", true, false, false},
    {"withgoogle.com", true, false, false},
    {"youtu.be", true, false, false},
    {"youtube-3rd-party.com", true, false, false},
    {"youtube-nocookie.com", true, false, false},
    {"youtube.ae", true, false, false},
    {"youtube.al", true, false, false},
    {"youtube.am", true, false, false},
    {"youtube.at", true, false, false},
    {"youtube.az", true, false, false},
    {"youtube.ba", true, false, false},
    {"youtube.be", true, false, false},
    {"youtube.bg", true, false, false},
    {"youtube.bh", true, false, false},
    {"youtube.bo", true, false, false},
    {"youtube.ca", true, false, false},
    {"youtube.cat", true, false, false},
    {"youtube.ch", true, false, false},
    {"youtube.cl", true, false, false},
    {"youtube.co", true, false, false},
    {"youtube.co.ae", true, false, false},
    {"youtube.co.at", true, false, false},
    {"youtube.co.hu", true, false, false},
    {"youtube.co.id", true, false, false},
    {"youtube.co.il", true, false, false},
    {"youtube.co.in", true, false, false},
    {"youtube.co.jp", true, false, false},
    {"youtube.co.ke", true, false, false},
    {"youtube.co.kr", true, false, false},
    {"youtube.co.ma", true, false, false},
    {"youtube.co.nz", true, false, false},
    {"youtube.co.th", true, false, false},
    {"youtube.co.ug", true, false, false},
    {"youtube.co.uk", true, false, false},
    {"youtube.co.ve", true, false, false},
    {"youtube.co.za", true, false, false},
    {"youtube.com", true, false, false},
    {"youtube.com.ar", true, false, false},
    {"youtube.com.au", true, false, false},
    {"youtube.com.az", true, false, false},
    {"youtube.com.bh", true, false, false},
    {"youtube.com.bo", true, false, false},
    {"youtube.com.br", true, false, false},
    {"youtube.com.by", true, false, false},
    {"youtube.com.co", true, false, false},
    {"youtube.com.do", true, false, false},
    {"youtube.com.ee", true, false, false},
    {"youtube.com.eg", true, false, false},
    {"youtube.com.es", true, false, false},
    {"youtube.com.gh", true, false, false},
    {"youtube.com.gr", true, false, false},
    {"youtube.com.gt", true, false, false},
    {"youtube.com.hk", true, false, false},
    {"youtube.com.hr", true, false, false},
    {"youtube.com.jm", true, false, false},
    {"youtube.com.jo", true, false, false},
    {"youtube.com.kw", true, false, false},
    {"youtube.com.lb", true, false, false},
    {"youtube.com.lv", true, false, false},
    {"youtube.com.mk", true, false, false},
    {"youtube.com.mt", true, false, false},
    {"youtube.com.mx", true, false, false},
    {"youtube.com.my", true, false, false},
    {"youtube.com.ng", true, false, false},
    {"youtube.com.om", true, false, false},
    {"youtube.com.pe", true, false, false},
    {"youtube.com.ph", true, false, false},
    {"youtube.com.pk", true, false, false},
    {"youtube.com.pt", true, false, false},
    {"youtube.com.qa", true, false, false},
    {"youtube.com.ro", true, false, false},
    {"youtube.com.sa", true, false, false},
    {"youtube.com.sg", true, false, false},
    {"youtube.com.tn", true, false, false},
    {"youtube.com.tr", true, false, false},
    {"youtube.com.tw", true, false, false},
    {"youtube.com.ua", true, false, false},
    {"youtube.com.uy", true, false, false},
    {"youtube.com.ve", true, false, false},
    {"youtube.cz", true, false, false},
    {"youtube.de", true, false, false},
    {"youtube.dk", true, false, false},
    {"youtube.ee", true, false, false},
    {"youtube.es", true, false, false},
    {"youtube.fi", true, false, false},
    {"youtube.fr", true, false, false},
    {"youtube.ge", true, false, false},
    {"youtube.gr", true, false, false},
    {"youtube.gt", true, false, false},
    {"youtube.hk", true, false, false},
    {"youtube.hr", true, false, false},
    {"youtube.hu", true, false, false},
    {"youtube.ie", true, false, false},
    {"youtube.in", true, false, false},
    {"youtube.is", true, false, false},
    {"youtube.it", true, false, false},
    {"youtube.jo", true, false, false},
    {"youtube.jp", true, false, false},
    {"youtube.kr", true, false, false},
    {"youtube.lk", true, false, false},
    {"youtube.lt", true, false, false},
    {"youtube.lv", true, false, false},
    {"youtube.ma", true, false, false},
    {"youtube.md", true, false, false},
    {"youtube.me", true, false, false},
    {"youtube.mk", true, false, false},
    {"youtube.mx", true, false, false},
    {"youtube.my", true, false, false},
    {"youtube.ng", true, false, false},
    {"youtube.nl", true, false, false},
    {"youtube.no", true, false, false},
    {"youtube.pe", true, false, false},
    {"youtube.ph", true, false, false},
    {"youtube.pk", true, false, false},
    {"youtube.pl", true, false, false},
    {"youtube.pr", true, false, false},
    {"youtube.pt", true, false, false},
    {"youtube.qa", true, false, false},
    {"youtube.ro", true, false, false},
    {"youtube.rs", true, false, false},
    {"youtube.ru", true, false, false},
    {"youtube.sa", true, false, false},
    {"youtube.se", true, false, false},
    {"youtube.sg", true, false, false},
    {"youtube.si", true, false, false},
    {"youtube.sk", true, false, false},
    {"youtube.sn", true, false, false},
    {"youtube.tn", true, false, false},
    {"youtube.ua", true, false, false},
    {"youtube.ug", true, false, false},
    {"youtube.uy", true, false, false},
    {"youtube.vn", true, false, false},
    {"youtubeeducation.com", true, false, false},
    {"youtubemobilesupport.com", true, false, false},
    {"ytimg.com", true, false, false},

    // Origins without subdomains and with same-origin collectors.
    {"accounts.google.com", false, true, false},
    {"apis.google.com", false, true, false},
    {"app.google.stackdriver.com", false, true, false},
    {"b.mail.google.com", false, true, false},
    {"chatenabled.mail.google.com", false, true, false},
    {"ddm.google.com", false, true, false},
    {"gmail.com", false, true, false},
    {"gmail.google.com", false, true, false},
    {"mail-attachment.googleusercontent.com", false, true, false},
    {"mail.google.com", false, true, false},
    {"www.gmail.com", false, true, false},

    // Origins without subdomains or same-origin collectors.
    {"ad.doubleclick.net", false, false, false},
    {"drive.google.com", false, false, false},
    {"redirector.googlevideo.com", false, false, false},
};

const char* const kGoogleStandardCollectors[] = {
    "https://beacons.gcp.gvt2.com/domainreliability/upload",
    "https://beacons.gvt2.com/domainreliability/upload",
    "https://beacons2.gvt2.com/domainreliability/upload",
    "https://beacons3.gvt2.com/domainreliability/upload",
    "https://beacons4.gvt2.com/domainreliability/upload",
    "https://beacons5.gvt2.com/domainreliability/upload",
    "https://beacons5.gvt3.com/domainreliability/upload",
    "https://clients2.google.com/domainreliability/upload",
};

const char* const kGoogleOriginSpecificCollectorPathString =
    "/domainreliability/upload";

std::unique_ptr<const DomainReliabilityConfig> CreateGoogleConfig(
    const GoogleConfigParams& params,
    bool is_www) {
  if (is_www)
    DCHECK(params.duplicate_for_www);

  std::string hostname = (is_www ? "www." : "") + std::string(params.hostname);
  bool include_subdomains = params.include_subdomains && !is_www;

  auto config = std::make_unique<DomainReliabilityConfig>();
  config->origin = GURL("https://" + hostname + "/");
  config->include_subdomains = include_subdomains;
  config->collectors.clear();
  if (params.include_origin_specific_collector) {
    GURL::Replacements replacements;
    replacements.SetPathStr(kGoogleOriginSpecificCollectorPathString);
    config->collectors.push_back(
        std::make_unique<GURL>(config->origin.ReplaceComponents(replacements)));
  }
  for (const char* collector : kGoogleStandardCollectors) {
    config->collectors.push_back(std::make_unique<GURL>(collector));
  }
  config->success_sample_rate = 0.05;
  config->failure_sample_rate = 1.00;
  config->path_prefixes.clear();
  return config;
}

}  // namespace

std::unique_ptr<const DomainReliabilityConfig> MaybeGetGoogleConfig(
    const std::string& hostname) {
  bool is_www_subdomain =
      base::StartsWith(hostname, "www.", base::CompareCase::SENSITIVE);
  std::string hostname_parent = net::GetSuperdomain(hostname);

  std::unique_ptr<const DomainReliabilityConfig> config;
  std::unique_ptr<const DomainReliabilityConfig> superdomain_config;

  for (const auto& params : kGoogleConfigs) {
    if (params.hostname == hostname) {
      config = CreateGoogleConfig(params, false);
      break;
    }
    if (params.duplicate_for_www && is_www_subdomain &&
        params.hostname == hostname_parent) {
      config = CreateGoogleConfig(params, true);
      break;
    }
    // Don't break out of the loop upon finding a superdomain config, because
    // there might be an exact match later on.
    if (params.include_subdomains && params.hostname == hostname_parent) {
      superdomain_config = CreateGoogleConfig(params, false);
    }
  }

  if (config) {
    DCHECK(config->origin.host() == hostname);
    return config;
  }

  if (!superdomain_config)
    return nullptr;

  DCHECK(superdomain_config->origin.host() == hostname_parent);
  DCHECK(superdomain_config->include_subdomains);

  return superdomain_config;
}

std::vector<std::unique_ptr<const DomainReliabilityConfig>>
GetAllGoogleConfigsForTesting() {
  std::vector<std::unique_ptr<const DomainReliabilityConfig>> configs_out;

  for (const auto& params : kGoogleConfigs) {
    configs_out.push_back(CreateGoogleConfig(params, false));
    if (params.duplicate_for_www)
      configs_out.push_back(CreateGoogleConfig(params, true));
  }
  return configs_out;
}

}  // namespace domain_reliability
